#pragma once
#pragma once
#include<vector>
#include <atomic>
#include<unordered_map>
#include<windows.h>
#include<iostream>
#include<thread>
#include<mutex>
#include<assert.h>
#include<time.h>
#include<algorithm>
using std::cout;
using std::end;
static const size_t Max_Bytes = 256 * 1024;
static const size_t NFREELIST = 208;
static const size_t NPAGE = 129;
static const size_t PAGE_SHIFT = 13;//8字节
#ifdef _WIN64
typedef unsigned long long PAGE_ID;
#elif _WIN32
	typedef size_t PAGE_ID;
#endif
	
// 直接去堆上按页申请空间
inline static void* SystemAlloc(size_t kpage)
{
#ifdef _WIN32						
		void* ptr = VirtualAlloc(0, kpage << 13, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);//一页8KB
#else
		// linux下brk mmap等
#endif

		if (ptr == nullptr)
			throw std::bad_alloc();
		return ptr;
}
//释放空间到堆
inline static void SystemFree(void* ptr)
{
#ifdef _WIN32
	VirtualFree(ptr, 0, MEM_RELEASE);
#else
	// sbrk unmmap等
#endif
}

static void*& Nextobj(void* obj)
{
	return *(void**)obj;
}
//调试技巧
//1.条件断点，疑似死循环，全部中断程序会在死循环处停下来
//2.查看栈帧
class FreeList
{
public:
	void Push(void* obj)
	{
		assert(obj);
		Nextobj(obj) = _freelist;
		_freelist = obj;
		++_size;
	}
	void PushRange(void* start, void* end,size_t n)
	{
		Nextobj(end) = _freelist;
		_freelist = start;
		_size += n;
	}
	void PopRange(void*& start, void*& end, size_t n)
	{
		assert(_size >= n);
		start = _freelist;
		end = start;
		for (size_t i = 0; i < n - 1; ++i)
		{
			end = Nextobj(end);
		}
		_freelist = Nextobj(end);
		Nextobj(end) = nullptr;
		_size -= n;
	}
	size_t Size()
	{
		return _size;
	}
	void* Pop()
	{
		assert(_freelist);
		void* obj = _freelist;
		_freelist = Nextobj(obj);
		--_size;
		return obj;
	}
	bool empty()
	{
		if (this == nullptr)
		{
			return true;
		}
		return _freelist == nullptr;
	}
	size_t& Maxsize()
	{
		return _maxsize;
	}

private:
	void* _freelist=nullptr;
	size_t _maxsize=1;
	size_t _size=0;
};
//计算对齐映射规则
class sizeClass
{
public:
	// 整体控制在最多10%左右的内碎片浪费
	// [1,128]					8byte对齐	    freelist[0,16)
	// [128+1,1024]				16byte对齐	    freelist[16,72)
	// [1024+1,8*1024]			128byte对齐	    freelist[72,128)
	// [8*1024+1,64*1024]		1024byte对齐     freelist[128,184)
	// [64*1024+1,256*1024]		8*1024byte对齐   freelist[184,208)
	
	//获取向下对齐到哪
	//size_t _RoundUp(size_t size, int align)
	//{
	//	size_t ret;
	//	if (size % align != 0)
	//	{
	//		ret = (size / align + 1) * align;
	//	}
	//	else
	//	{
	//		ret = size;
	//	}
	//	return ret;
	//}
	static inline size_t _RoundUp(size_t size, int align)
	{
		return (size + align - 1) & ~(align - 1);
	}
	static inline size_t RoundUp(size_t size)
	{
		if (size <= 128)
		{
			return _RoundUp(size, 8);
		}
		else if (size <= 1024)
		{
			return _RoundUp(size, 16);
		}
		else if (size <= 8 * 1024)
		{
			return _RoundUp(size, 128);
		}
		else if (size <= 64 * 1024)
		{
			return _RoundUp(size, 1024);
		}
		else if(size <= 256*1024)
		{
			return _RoundUp(size, 8*1024);
		}
		else
		{
			return _RoundUp(size,1<<PAGE_SHIFT);
		}
	}
	//计算落在哪一个桶内
	static inline size_t _Index(size_t byte, size_t allign_shift)//2的n次方
	{
		return ((byte + (1 << allign_shift) - 1) >>allign_shift) - 1;
	}
	static inline size_t Index(size_t  byte)
	{
		assert(byte <= Max_Bytes);
		//每个区间有多少桶
		static int arr[] = {16,56,56,56};
		if (byte <= 128)
		{
			return _Index(byte,3);
		}
		else if (byte <= 1024)
		{
			return _RoundUp(byte-128,4)+arr[0];
		}
		else if (byte <= 8 * 1024)
		{
			return _RoundUp(byte-1024,7 )+arr[1];
		}
		else if (byte <= 64 * 1024)
		{
			return _RoundUp(byte-8*1024,10 )+arr[2];
		}
		else
		{
			return _RoundUp(byte-64*1024, 13)+arr[3];
		}
	}
	//一次从中心缓存取得上限
	static inline size_t NumMoveSize(size_t size)
	{
		assert(size > 0);
		int num = Max_Bytes / size;
		if (num < 2)//最少2
			num = 2;
		if (num > 512)//最多512个
			num = 512;
		return num;
	}
	//计算一次向系统要多少页
	//最多256kb
	//一页8KB
	static inline size_t NumMovePage(size_t size)
	{
		size_t num = NumMoveSize(size);
		size_t npage = num * size;
		npage >>= 13;
		if (npage == 0)
			npage = 1;
		return npage;
	}

private:
};
//管理连续页大块内存的跨度结构 结点
struct Span
{
	PAGE_ID _pageId=0;//大块内存起始页的页号
	size_t _n=0;//页的数量

	Span* _next=nullptr;//双向链表
	Span* _prev=nullptr;

	size_t _objsize = 0;//切好的小对象的大小
	size_t _usecount=0;//切好小块内存，被分配给thread_cache的数量
	void* _freelist=nullptr;//切好的小块内存的自由链表
	bool isuse = false;//是否被使用
};
//双向带头链表
class SpanList
{
public:
	Span* begin()
	{
		return _head->_next;
	}
	Span* end()
	{
		return _head;
	}
	bool Empty()
	{
		return _head == _head->_next;
	}
	SpanList()
	{
		_head = new Span();
		_head->_next = _head;
		_head->_prev = _head;
	}
	void PushFront(Span* span)
	{
		Insert(begin(), span);
	}
	Span* PopFront()
	{
		Span* front = _head->_next;
		Erase(front);
		return front;
	}
	void Insert(Span* pos,Span* newSpan)
	{
		assert(pos);
		assert(newSpan);
		Span* prev = pos->_prev;
		prev->_next = newSpan;
		newSpan->_prev = prev;
		newSpan->_next = pos;
		pos->_prev = newSpan;
	}
	void Erase(Span* pos)
	{
		assert(pos);
		assert(pos != _head);

		Span* prev = pos->_prev;
		Span* next = pos->_next;
		prev->_next = next;
		next->_prev = prev;
	}
private:
	Span* _head;
public:
	std::mutex _mutex;
};